package com;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.facet.*;
import org.apache.lucene.facet.taxonomy.FastTaxonomyFacetCounts;
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.ByteBuffersDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NRTCachingDirectory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SimpleFacetExamples {

    ByteBuffersDirectory taxonomyDir = new ByteBuffersDirectory();
    ByteBuffersDirectory indexDir = new ByteBuffersDirectory();
    FacetsConfig facetsConfig = new FacetsConfig();


    public SimpleFacetExamples(){
        facetsConfig.setHierarchical("Publish Date",true);
    }
    public List<FacetResult> runFacetOnly() throws IOException {
        index();;
        return facetsOnly();
    }
    public List<FacetResult> runSimpleFacetSearch() throws IOException {
        index();;
        return facetsWithSearch();
    }
    public List<FacetResult> runDrillSideway() throws IOException {
        index();;
        return drillDownSide();
    }
    public List<FacetResult> runDrillDown() throws IOException {
        index();;
        return drillDown();
    }

    private void index() throws IOException {
        IndexWriterConfig config = new IndexWriterConfig(new WhitespaceAnalyzer()).setOpenMode(IndexWriterConfig.OpenMode.CREATE);
        IndexWriter indexWriter = new IndexWriter(indexDir, config);

        DirectoryTaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter(taxonomyDir);
        Document document = new Document();
        document.add(new FacetField("Author","joe"));;
        document.add(new FacetField("Publish Date","2020","10","09"));
        indexWriter.addDocument(facetsConfig.build(taxonomyWriter, document));
        Document document2 = new Document();
        document2.add(new FacetField("Author","john"));;
        document2.add(new FacetField("Publish Date","2021","07","25"));
        indexWriter.addDocument(facetsConfig.build(taxonomyWriter, document2));
        Document document3 = new Document();
        document3.add(new FacetField("Author","tom"));;
        document3.add(new FacetField("Publish Date","2020","04","30"));
        indexWriter.addDocument(facetsConfig.build(taxonomyWriter, document3));
        Document document4 = new Document();
        document4.add(new FacetField("Author","lucas"));;
        document4.add(new FacetField("Publish Date","2019","06","14"));
        indexWriter.addDocument(facetsConfig.build(taxonomyWriter, document4));
        Document document5 = new Document();
        document5.add(new FacetField("Author","tylor"));;
        document5.add(new FacetField("Publish Date","2018","04","05"));
        indexWriter.addDocument(facetsConfig.build(taxonomyWriter, document5));

        taxonomyWriter.close();
        indexWriter.close();;
    }
    private List<FacetResult> drillDown() throws IOException {
        List facetResults = new ArrayList<FacetResult>();
        DirectoryReader reader = DirectoryReader.open(indexDir);
        DirectoryTaxonomyReader directoryTaxonomyReader = new DirectoryTaxonomyReader(taxonomyDir);
        IndexSearcher indexSearcher = new IndexSearcher(reader);

        DrillDownQuery drillDownQuery = new DrillDownQuery(facetsConfig);
        drillDownQuery.add("Publish Date","2020");
        FacetsCollector facetsCollector = new FacetsCollector();

        FacetsCollector.search(indexSearcher,drillDownQuery,10,facetsCollector);

        FastTaxonomyFacetCounts fastTaxonomyFacetCounts = new FastTaxonomyFacetCounts(directoryTaxonomyReader, facetsConfig, facetsCollector);
        facetResults.add(fastTaxonomyFacetCounts.getTopChildren( 10,"Author"));

        directoryTaxonomyReader.close();;
        reader.close();
        return facetResults;

    }
    private List<FacetResult> drillDownSide() throws IOException {
        DirectoryReader reader = DirectoryReader.open(indexDir);
        DirectoryTaxonomyReader directoryTaxonomyReader = new DirectoryTaxonomyReader(taxonomyDir);
        IndexSearcher indexSearcher = new IndexSearcher(reader);

        DrillDownQuery drillDownQuery = new DrillDownQuery(facetsConfig);
        drillDownQuery.add("Publish Date","2020");

        DrillSideways drillSideways = new DrillSideways(indexSearcher, facetsConfig, directoryTaxonomyReader);
        DrillSideways.DrillSidewaysResult search = drillSideways.search(drillDownQuery, 10);
        List<FacetResult> allDims = search.facets.getAllDims(10);

        reader.close();
        directoryTaxonomyReader.close();
        return allDims;
    }
    /** User runs a query and counts facets  with collecting the matching documents. */
    private List<FacetResult> facetsWithSearch() throws IOException {
        List facetResults = new ArrayList<FacetResult>();
        DirectoryReader reader = DirectoryReader.open(indexDir);
        IndexSearcher indexSearcher = new IndexSearcher(reader);

        FacetsCollector facetsCollector = new FacetsCollector();

        FacetsCollector.search(indexSearcher,new MatchAllDocsQuery(),10,facetsCollector);

        DirectoryTaxonomyReader directoryTaxonomyReader = new DirectoryTaxonomyReader(taxonomyDir);
        FastTaxonomyFacetCounts fastTaxonomyFacetCounts = new FastTaxonomyFacetCounts(directoryTaxonomyReader, facetsConfig, facetsCollector);

        facetResults.add(fastTaxonomyFacetCounts.getTopChildren(10,"Author"));
        facetResults.add(fastTaxonomyFacetCounts.getTopChildren(10,"Publish Date"));

        reader.close();
        directoryTaxonomyReader.close();;
        return facetResults;
    }
    /** User runs a query and counts facets only without collecting the matching documents. */
    private List<FacetResult> facetsOnly() throws IOException {
        List facetResults = new ArrayList<FacetResult>();
        DirectoryReader reader = DirectoryReader.open(indexDir);
        IndexSearcher indexSearcher = new IndexSearcher(reader);
        FacetsCollector fc = indexSearcher.search(new MatchAllDocsQuery(), new FacetsCollectorManager());

        DirectoryTaxonomyReader directoryTaxonomyReader = new DirectoryTaxonomyReader(taxonomyDir);
        FastTaxonomyFacetCounts fastTaxonomyFacetCounts = new FastTaxonomyFacetCounts(directoryTaxonomyReader, facetsConfig, fc);

        facetResults.add(fastTaxonomyFacetCounts.getTopChildren(10,"Author"));
        facetResults.add(fastTaxonomyFacetCounts.getTopChildren(10,"Publish Date"));

        reader.close();
        directoryTaxonomyReader.close();;
        return facetResults;
    }

}
